//! 指纹识别核心功能模块
//! 提供Web服务技术指纹识别的基础功能

use anyhow::{anyhow, Context, Result};
use log::{debug, error, info, warn};
use regex::Regex;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::fs;
use std::fs::File;
use std::io::{BufReader, Read};
use std::path::{Path, PathBuf};
use once_cell::sync::Lazy;

/// 指纹匹配条件结构定义
#[derive(Debug, Deserialize, Clone, Serialize)]
pub struct FingerprintCondition {
    /// 状态码匹配列表
    #[serde(default)]
    pub status: Vec<u16>,
    /// 响应头匹配列表
    #[serde(default)]
    pub header: HashMap<String, String>,
    /// 响应头正则匹配列表
    #[serde(default)]
    pub header_regex: HashMap<String, String>,
    /// 关键词匹配列表
    #[serde(default)]
    pub keyword: Vec<String>,
    /// 正则表达式匹配列表
    #[serde(default)]
    pub regex: Vec<String>,
    /// URL路径匹配
    #[serde(default)]
    pub path: String,
}

/// 指纹信息结构定义
#[derive(Debug, Deserialize, Clone, Serialize, PartialEq, Eq, Hash)]
pub struct FingerprintInfo {
    /// 指纹ID
    pub id: String,
    /// 技术名称
    pub name: String,
    /// 技术类型（web框架、服务器、语言等）
    pub category: String,
    /// 版本信息
    #[serde(default)]
    pub version: String,
    /// 描述信息
    #[serde(default)]
    pub description: String,
}

/// 指纹规则结构定义
#[derive(Debug, Deserialize, Clone, Serialize)]
pub struct FingerprintRule {
    /// 指纹信息
    pub info: FingerprintInfo,
    /// 匹配条件
    pub conditions: Vec<FingerprintCondition>,
    /// 匹配逻辑（and/or）
    #[serde(default = "default_match_logic")]
    pub match_logic: String,
}

/// 兼容JSON格式的指纹规则结构
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct JsonFingerprintRule {
    pub cms: String,
    pub method: String,
    pub location: String,
    pub keyword: Vec<String>,
    pub isImportant: bool,
    pub type_: String, // 注意：在JSON中可能是"type"，我们使用type_避免关键字冲突
}

/// JSON指纹规则根结构
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct JsonFingerprintRoot {
    pub fingerprint: Vec<JsonFingerprintRule>,
}

fn default_match_logic() -> String {
    "or".to_string()
}

/// 响应信息结构定义
#[derive(Debug, Clone)]
pub struct ResponseInfo {
    /// 响应状态码
    pub status: u16,
    /// 响应头信息
    pub headers: HashMap<String, String>,
    /// 响应体内容
    pub body: String,
    /// 响应URL
    pub url: String,
}

/// 识别结果结构定义
#[derive(Debug, Clone, Serialize)]
pub struct FingerprintResult {
    /// 目标URL
    pub target: String,
    /// 识别到的技术列表
    pub technologies: Vec<FingerprintInfo>,
    /// 识别时间
    pub identified_at: String,
}

/// 指纹识别核心引擎
#[derive(Debug, Clone)]
pub struct FingerprintCoreEngine {
    /// 已加载的指纹规则
    pub rules: HashMap<String, FingerprintRule>,
}

impl FingerprintCoreEngine {
    /// 创建新的指纹识别核心引擎实例
    pub fn new() -> Self {
        Self {
            rules: HashMap::new(),
        }
    }

    /// 从文件加载指纹规则（YAML格式）
    pub fn load_rule(&mut self, file_path: &str) -> Result<()> {
        debug!("[Fingerprint] Loading YAML rule from: {}", file_path);
        
        let content = fs::read_to_string(file_path)?;
        let rule: FingerprintRule = serde_yaml::from_str(&content)?;

        // 保存ID和名称用于日志输出
        let rule_id = rule.info.id.clone();
        let rule_name = rule.info.name.clone();
        self.rules.insert(rule_id.clone(), rule);
        debug!("[Fingerprint] Successfully loaded YAML rule: {} ({})", rule_id, rule_name);
        Ok(())
    }

    /// 从JSON文件加载指纹规则
    pub fn load_rule_from_json(&mut self, file_path: &str) -> Result<()> {
        debug!("[Fingerprint] Loading JSON rules from: {}", file_path);
        
        let file = File::open(file_path)?;
        let reader = BufReader::new(file);
        
        // 解析JSON格式的指纹规则
        let json_root = serde_json::from_reader::<_, JsonFingerprintRoot>(reader)?;
        
        // 保存规则数量用于日志输出
        let rule_count = json_root.fingerprint.len();
        
        // 转换JSON格式规则为我们的标准格式 - 使用引用迭代以保留所有权
        for json_rule in &json_root.fingerprint {
            // 创建指纹信息
            let info = FingerprintInfo {
                id: format!("json_{}", json_rule.cms),
                name: json_rule.cms.clone(),
                category: json_rule.type_.clone(),
                version: String::new(),
                description: format!("Imported from JSON fingerprint rule"),
            };
            
            // 创建匹配条件
            let mut condition = FingerprintCondition {
                status: Vec::new(),
                header: HashMap::new(),
                header_regex: HashMap::new(),
                keyword: Vec::new(),
                regex: Vec::new(),
                path: String::new(),
            };
            
            // 根据location设置不同的匹配方式
            match json_rule.location.as_str() {
                "header" => {
                    // 头部匹配 - 处理为header_regex
                    for keyword in &json_rule.keyword {
                        // 对于header类型，keyword通常格式为"X-Powered-By: PHP"
                        if let Some((header_name, header_value)) = keyword.split_once(':') {
                            condition.header_regex.insert(
                                header_name.trim().to_string(),
                                header_value.trim().to_string(),
                            );
                        }
                    }
                },
                "body" | "title" => {
                    // 正文或标题匹配 - 处理为keyword或regex
                    if json_rule.method == "keyword" {
                        condition.keyword.extend(json_rule.keyword.clone());
                    } else {
                        condition.regex.extend(json_rule.keyword.clone());
                    }
                },
                _ => {
                    // 其他情况作为keyword处理
                    condition.keyword.extend(json_rule.keyword.clone());
                }
            }
            
            // 创建并添加规则
            let rule = FingerprintRule {
                info,
                conditions: vec![condition],
                match_logic: "or".to_string(),
            };
            
            self.rules.insert(rule.info.id.clone(), rule);
        }
        
        debug!("[Fingerprint] Successfully loaded {} JSON rules from {}", rule_count, file_path);
        Ok(())
    }

    /// 从目录加载多个指纹规则
    pub fn load_rules_from_dir(&mut self, dir_path: &str) -> Result<()> {
        let path = Path::new(dir_path);
        
        if !path.exists() || !path.is_dir() {
            return Err(anyhow!("Directory does not exist or is not a directory: {}", dir_path));
        }
        
        for entry in fs::read_dir(path)? {
            let entry = entry?;
            let file_path = entry.path();
            
            if let Some(ext) = file_path.extension() {
                let file_str = file_path.to_str().unwrap();
                if ext == "yml" || ext == "yaml" {
                    match self.load_rule(file_str) {
                        Ok(_) => {},
                        Err(e) => {
                            warn!("[Fingerprint] Failed to load YAML rule {}: {}", file_path.display(), e);
                        }
                    }
                } else if ext == "json" {
                    match self.load_rule_from_json(file_str) {
                        Ok(_) => {},
                        Err(e) => {
                            warn!("[Fingerprint] Failed to load JSON rule {}: {}", file_path.display(), e);
                        }
                    }
                }
            }
        }
        
        info!("[Fingerprint] Loaded {} rules from directory: {}", self.rules.len(), dir_path);
        Ok(())
    }

    /// 评估单个条件是否匹配
    pub fn evaluate_condition(&self, condition: &FingerprintCondition, response: &ResponseInfo) -> bool {
        // 检查状态码
        if !condition.status.is_empty() && !condition.status.contains(&response.status) {
            return false;
        }
        
        // 检查响应头完全匹配
        for (key, value) in &condition.header {
            if let Some(header_value) = response.headers.get(key) {
                if !header_value.to_lowercase().contains(&value.to_lowercase()) {
                    return false;
                }
            } else {
                return false;
            }
        }
        
        // 检查响应头正则匹配
        for (key, pattern) in &condition.header_regex {
            if let Some(header_value) = response.headers.get(key) {
                if let Ok(regex) = Regex::new(pattern) {
                    if !regex.is_match(header_value) {
                        return false;
                    }
                }
            } else {
                return false;
            }
        }
        
        // 检查关键词
        for keyword in &condition.keyword {
            if !response.body.to_lowercase().contains(&keyword.to_lowercase()) {
                return false;
            }
        }
        
        // 检查正则表达式
        for pattern in &condition.regex {
            if let Ok(regex) = Regex::new(pattern) {
                if !regex.is_match(&response.body) {
                    return false;
                }
            }
        }
        
        true
    }

    /// 评估单个规则是否匹配
    pub fn evaluate_rule(&self, rule: &FingerprintRule, response: &ResponseInfo) -> bool {
        if rule.conditions.is_empty() {
            return false;
        }
        
        if rule.match_logic.to_lowercase() == "and" {
            // AND逻辑：所有条件都必须匹配
            rule.conditions.iter().all(|cond| self.evaluate_condition(cond, response))
        } else {
            // OR逻辑：任一条件匹配即可
            rule.conditions.iter().any(|cond| self.evaluate_condition(cond, response))
        }
    }

    /// 识别响应中的技术指纹
    pub fn identify_fingerprints(&self, response: &ResponseInfo) -> Vec<FingerprintInfo> {
        let mut identified_technologies = Vec::new();
        
        for rule in self.rules.values() {
            if self.evaluate_rule(rule, response) {
                identified_technologies.push(rule.info.clone());
                debug!("[Fingerprint] Matched rule: {} (Technology: {}, Category: {}) for {}", 
                       rule.info.id, rule.info.name, rule.info.category, response.url);
            }
        }
        
        identified_technologies
    }

    /// 从原始HTTP响应解析响应信息
    pub fn parse_response(&self, status: u16, headers: &http::HeaderMap, body: &str, url: &str) -> ResponseInfo {
        debug!("[Fingerprint] Parsing HTTP response for fingerprint analysis: {} (status: {})", url, status);

        let mut response_headers = HashMap::new();
        
        for (key, value) in headers {
            if let Ok(value_str) = value.to_str() {
                response_headers.insert(key.as_str().to_string(), value_str.to_string());
            }
        }
        
        ResponseInfo {
            status,
            headers: response_headers,
            body: body.to_string(),
            url: url.to_string(),
        }
    }
}
